#pragma once

#include <iostream>
#include <string>
#include <list>
#include <memory>
#include<algorithm>
#include <sys/socket.h>
#include "Log.hpp"
#include "InetAddr.hpp"
#include "Mutex.hpp"

using namespace MutexMoudle;
using namespace LogMoudule;
class UserInterFace
{
public:
    virtual ~UserInterFace() = default;
    virtual void SendTo(int sockfd, const std::string &message) = 0;
    virtual bool operator==(const InetAddr &u) = 0;
    virtual std::string Id()=0;
};

class User : public UserInterFace
{
public:
    User(const InetAddr &id) : _id(id)
    {
    }
    void SendTo(int sockfd, const std::string &message)
    {
        LOG(LogLevel::DEBUG) << "send message to " << _id.GetAddr() << " info: " << message;
        int n = ::sendto(sockfd, message.c_str(), message.size(), 0, _id.GetNetAddrPtr(), _id.GetNetAddrLen());
        (void)n;
    }
    bool operator==(const InetAddr &u)
    {
        return _id == u;
    }
     std::string Id()
    {
        return _id.GetAddr();
    }
    ~User()
    {
    }

private:
    InetAddr _id;
};

class UserManager
{
public:
    UserManager()
    {
    }
    
    void AddUser(InetAddr &id) 
    {
        LockGuard lockguard(_mutex);
        for (auto &user : _online_user)
        {
            if (*user == id)
            {
                LOG(LogLevel::INFO) << "用户已经存在";
                return;
            }
        }
        LOG(LogLevel::INFO) << "增添新用户";
        _online_user.push_back(std::make_shared<User>(id));
        Print();
    }
    void DelUser(InetAddr &user)
    {
        LockGuard lockguard(_mutex);
        auto pos=std::remove_if(_online_user.begin(),_online_user.end(),[&user]( std::shared_ptr<UserInterFace> &_user){ return *_user==user;});
        _online_user.erase(pos,_online_user.end());
        Print();
    }
    void Router(int sockfd, const std::string &message)
    {
        LockGuard lockguard(_mutex);
        for (auto &user : _online_user)
        {
            user->SendTo(sockfd, message);
        }
    }
    void Print()
    {
        for(auto &user:_online_user)
        {
            LOG(LogLevel::DEBUG)<<user->Id();
        }
    }
    ~UserManager()
    {
    }

private:
    std::list<std::shared_ptr<UserInterFace>> _online_user;
    Mutex _mutex;
};